package controller;

import java.io.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import model.QuestionType;
import model.UserGroup;

import core.*;

public class SystemConfig extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final String config_file = "/WEB-INF/config.xml";
	private static Properties p = new Properties();
	private static PgSQL db = PgSQL.getInstance();

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		UserGroup group = (UserGroup) session.getAttribute("usergroup");
		if(group == null){
			View.showMessage(request, response, "Please login first.", "Login");
		}else if(!group.isAdministrator()){
			View.showMessage(request, response, "Sorry, you are not permitted.", "Index");
		}else{
			LinkedList<QuestionType> question_types = getQuestionTypes();

			request.setAttribute("question_types[]", question_types.toArray(new QuestionType[0]));
			View.show(request, response, "system_config");
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		CurrentUser user = new CurrentUser(request);
		UserGroup group = user.getGroup();
		if(group == null){
			View.showMessage(request, response, "Please login first.", "Login");
			return;
		}else if(!group.isAdministrator()){
			View.showMessage(request, response, "Sorry, you are not permitted.", "Index");
			return;
		}

		if(request.getParameter("template") != null){
			Config.template = request.getParameter("template");
		}
		
		if(Config.encryptKey == null || Config.encryptKey.isEmpty()){
			String adminPassword = request.getParameter("adminPassword");
			if(adminPassword != null && !adminPassword.isEmpty()){
				Config.encryptKey = request.getParameter("encryptKey");
				user.changePassword("admin", adminPassword);
			}
		}
		
		Config.messageTimeout = Tool.intval(request.getParameter("messageTimeout"));
		Config.usernameMinLength = Tool.intval(request.getParameter("usernameMinLength"));
		Config.passwordMinLength = Tool.intval(request.getParameter("passwordMinLength"));
		Config.passwordMaxLength = Tool.intval(request.getParameter("passwordMaxLength"));
		Config.acceptablePaperSubmitDelay = Tool.intval(request.getParameter("acceptablePaperSubmitDelay"));
		
		saveConfig();
		
		ResultSet rs = db.query("SELECT qtid FROM qz_questiontype WHERE qtid!=0");
		ArrayList<Integer> original_ids = new ArrayList<Integer>();
		try {
			while(rs.next()){
				int id = rs.getInt(1);
				original_ids.add(id);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		String[] type_id = request.getParameterValues("questiontype_qtid[]");
		String[] type_name = request.getParameterValues("questiontype_name[]");
		String[] type_parent = request.getParameterValues("questiontype_parenttype[]");
		
		ArrayList<Integer> current_ids = new ArrayList<Integer>();
		for(int i = 0; i < type_id.length; i++){
			if(type_id[i] == null || type_id[i].isEmpty()){
				PreparedStatement ps = db.prepareStatement("INSERT INTO qz_questiontype VALUES (nextval('qtid'), ?, ?)");
				try{
					ps.setString(1, type_name[i]);
					ps.setInt(2, Tool.intval(type_parent[i]));
					ps.executeUpdate();
				}catch(SQLException e){
					e.printStackTrace();
				}
			}else{
				current_ids.add(Tool.intval(type_id[i]));
				
				PreparedStatement ps = db.prepareStatement("UPDATE qz_questiontype SET name=?, parent_type=? WHERE qtid=?");
				try{
					ps.setString(1, type_name[i]);
					ps.setInt(2, Tool.intval(type_parent[i]));
					ps.setInt(3, Tool.intval(type_id[i]));
					ps.executeUpdate();
				}catch(SQLException e){
					e.printStackTrace();
				}
			}
		}
		
		Iterator<Integer> iter = original_ids.iterator();
		while(iter.hasNext()){
			int id = iter.next();
			if(!current_ids.contains(id)){
				db.update("DELETE FROM qz_questiontype WHERE qtid=" + id);
			}
		}
		
		View.showMessage(request, response, "System config is saved.", "refresh");
	}
	
	public void init(){
		loadConfig();
	}
	
	protected void saveConfig(){
		p.setProperty("dbName", Config.dbName);
		if(Config.dbUser != null){
			p.setProperty("dbUser", Config.dbUser);
		}else{
			p.remove("dbUser");
		}
		if(Config.dbPassword != null){
			p.setProperty("dbPassword", Config.dbPassword);
		}else{
			p.remove("dbPassword");
		}
		
		p.setProperty("encryptKey", Config.encryptKey);
		
		p.setProperty("messageTimeout", Integer.toString(Config.messageTimeout));
		p.setProperty("template", Config.template);
		
		p.setProperty("usernameMinLength", Integer.toString(Config.usernameMinLength));
		p.setProperty("passwordMinLength", Integer.toString(Config.passwordMinLength));
		p.setProperty("passwordMaxLength", Integer.toString(Config.passwordMaxLength));
		p.setProperty("acceptablePaperSubmitDelay", Integer.toString(Config.acceptablePaperSubmitDelay));
		
		try {
			p.storeToXML(new FileOutputStream(getServletContext().getRealPath(config_file)), null);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	protected void loadConfig(){
		try {
			p.loadFromXML(new FileInputStream(getServletContext().getRealPath(config_file)));
		} catch (InvalidPropertiesFormatException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			saveConfig();
		} catch (IOException e) {
			e.printStackTrace();
		}

		Config.dbName = p.getProperty("dbName");
		if(p.contains("dbUser")){
			Config.dbUser = p.getProperty("dbUser");
		}
		if(p.contains("dbPassword")){
			Config.dbPassword = p.getProperty("dbPassword");
		}
		
		Config.encryptKey = p.getProperty("encryptKey");
		
		Config.messageTimeout = Tool.intval(p.getProperty("messageTimeout"));
		Config.template = p.getProperty("template");
		
		Config.usernameMinLength = Tool.intval(p.getProperty("usernameMinLength"));
		Config.passwordMinLength = Tool.intval(p.getProperty("passwordMinLength"));
		Config.passwordMaxLength = Tool.intval(p.getProperty("passwordMaxLength"));
		Config.acceptablePaperSubmitDelay = Tool.intval(p.getProperty("acceptablePaperSubmitDelay"));
	}
	
	protected LinkedList<QuestionType> getQuestionTypes(){
		LinkedList<QuestionType> question_types = new LinkedList<QuestionType>();
		ResultSet rs = db.query("SELECT * FROM qz_questiontype");
		try{
			while(rs.next()){
				QuestionType t = new QuestionType();
				t.setQtid(rs.getInt(1));
				t.setName(rs.getString(2));
				t.setParentType(rs.getInt(3));
				question_types.add(t);
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		
		return question_types;
	}
}
